﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace Dae2Png
{
	class Program
	{
		public static uint ColorTexture;
		public static uint DepthTexture;
		public static uint FBOHandle;


		static void Main(string[] args)
		{

			int width = 512;
			int height = 512;

			var hidden = new GameWindow(width, height, GraphicsMode.Default, "OpenTK | Hidden input window", GameWindowFlags.Default, DisplayDevice.Default);
			//hidden.Visible = false;
			//hidden.Load += hidden_Load;
			//hidden.Unload += hidden_Unload;
			//hidden.RenderFrame += hidden_RenderFrame;
			//hidden.Run(60.0, 0.0);

			GL.Disable(EnableCap.CullFace);

			GL.GenTextures(1, out ColorTexture);
			GL.BindTexture(TextureTarget.Texture2D, ColorTexture);
			GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);

			GL.GenTextures(1, out DepthTexture);
			GL.BindTexture(TextureTarget.Texture2D, DepthTexture);
			GL.TexImage2D(TextureTarget.Texture2D, 0, (PixelInternalFormat)All.DepthComponent32, width, height, 0, OpenTK.Graphics.OpenGL.PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
			// things go horribly wrong if DepthComponent's Bitcount does not match the main Framebuffer's Depth
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);

			GL.Ext.GenFramebuffers(1, out FBOHandle);
			GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, FBOHandle);
			GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, ColorTexture, 0);
			GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, TextureTarget.Texture2D, DepthTexture, 0);

			GL.Viewport(0, 0, width, height);

			// clear the screen in red, to make it very obvious what the clear affected. only the FBO, not the real framebuffer
			GL.ClearColor(1f, 0f, 0f, 0f);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

			// smack 50 random triangles into the FBO's textures
			GL.Begin(BeginMode.Triangles);
			{
				for (int i = 0; i < 50; i++)
				{
					GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
					GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
					GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
					GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
					GL.Color3(GetRandom0to1(), GetRandom0to1(), GetRandom0to1());
					GL.Vertex3(GetRandom(), GetRandom(), GetRandom());
				}
			}
			GL.End();
			//GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);

			//GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
			Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			BitmapData data = bmp.LockBits(
					new Rectangle(0, 0, width, height),
					ImageLockMode.WriteOnly,
					System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			GL.ReadPixels(0, 0, width, height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
			bmp.UnlockBits(data);
			bmp.Save("1.png");
		}

		static Random rnd = new Random();
		public const float scale = 0.3f;

		/// <summary>Returns a random Float in the range [-0.5*scale..+0.5*scale]</summary>
		public static float GetRandom()
		{
			return (float)(rnd.NextDouble() - 0.5) * scale;
		}

		/// <summary>Returns a random Float in the range [0..1]</summary>
		public static float GetRandom0to1()
		{
			return (float)rnd.NextDouble();
		}

	}
}
